
import re
import json
import pandas as pd
import pickle
from datetime import datetime
from dicttoxml import dicttoxml
from xml.dom.minidom import parseString

from abc import ABC, abstractmethod


class Person(ABC):
    def __init__(self, name, pid):
        self._name = name
        self.__pid = pid

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    @property
    def pid(self):
        return self.__pid

    @abstractmethod
    def display_info(self):
        pass


class Student(Person):
    def __init__(self, name, stuid, gender, ethnicity, class_info, major):
        super().__init__(name, stuid)
        self._gender = gender
        self.ethnicity =ethnicity
        self.class_info = class_info
        self.major = major
        self.dormitory = None

    def display_info(self):
        print(
            f"姓名: {self._name}, 学号: {self.pid}, 性别: {self._gender}, 民族: {self._ethnicity}, 班级: {self._class_info}, 专业: {self._major}")

    def to_dict(self):
        return {
            "name": self._name,
            "stuid": self.pid,
            "gender": self._gender,
            "ethnicity": self.ethnicity,
            "class_info": self.class_info,
            "major": self.major
        }


class teacher(Person):
    def __init__(self, name, id):
        super().__init__(name, id)

    def display_info(self):
        print(f"姓名: {self._name}, 工号: {self.pid}")

    def add_student(self, students):
        while True:
            name = input("学生姓名：")
            student_id = input("学号（4位数字）")
            if not re.match(r'^\d{4}$', student_id):
                print("学号必须是4位数字，请重新输入")
                continue
            gender = input("性别：1男，2女")
            if gender == "1":
                gender = "男"
            elif gender == "2":
                gender = "女"
            else:
                print("输入无效，请重新输入")
                continue
            ethnicity_choice = input("民族：1汉 2维吾尔 3 哈萨克 4藏族 5其它")
            ethnicities = {'1': "汉", "2": "维吾尔", "3": "哈萨克", "4": "藏族", "5": "其它"}
            ethnicity = ethnicities[ethnicity_choice]
            class_info = input("班级：")
            major = input("专业：")
            student = Student(name, student_id, gender, ethnicity, class_info, major)
            students.append(student)

            create_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            log_file = {"姓名": self.name, "工号": self.pid, "操作": "添加" + name + "的学生信息", "时间": create_time}

            quit_add = input("0、退出    1、继续添加")
            if quit_add == "0":
                student_dicts = [student.to_dict() for student in students]
                students_data = json.dumps(student_dicts, ensure_ascii=False, indent=4)
                try:
                    with open('students_data.json', 'r', encoding='utf-8') as f:
                        existing_data = json.load(f)
                except FileNotFoundError:
                    existing_data = []
                combined_data = existing_data + student_dicts
                with open('students_data.json', 'w', encoding='utf-8') as f:
                    json.dump(combined_data, f, ensure_ascii=False, indent=4)

                xml_data = dicttoxml(log_file)
                dom = parseString(xml_data)
                xml_str = dom.toprettyxml(indent="  ")

                with open('log.xml', 'a', encoding='utf-8') as f:
                    f.write(xml_str)
                break
            else:
                pass

    def alter_student(self):
        while True:
            try:
                with open('students_data.json', 'r', encoding='utf-8') as f:
                    data = json.load(f)
            except FileNotFoundError:
                print("文件未找到，请检查文件路径。")
                data = []
            alter_data = input("请输入要修改学生信息的姓名")
            for student in data:
                if student["name"] == alter_data:
                    student["stuid"] = input("请输入学号（4位数字）")
                    if not re.match(r'^\d{4}$', student["stuid"]):
                        print("学号必须是4位数字，请重新输入")
                        continue
                    gender = input("性别：1男，2女")
                    if gender == "1":
                        student['gender'] = "男"
                    elif gender == "2":
                        student['gender'] = "女"
                    else:
                        print("输入无效，请重新输入")
                        continue
                    ethnicity_choice = input("民族：1汉 2维吾尔 3 哈萨克 4藏族 5其它")
                    ethnicities = {'1': "汉", "2": "维吾尔", "3": "哈萨克", "4": "藏族", "5": "其它"}
                    student['ethnicity'] = ethnicities[ethnicity_choice]
                    student['class_info'] = input("班级：")
                    student['major'] = input("专业：")
                    print("修改成功!")
            alter_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            quit_alter = input("0、退出    1、继续修改")

            if quit_alter == "0":
                with open('students_data.json', 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=4)
                log_file = {"姓名": self.name, "工号": self.pid, "操作": "修改" + student["name"] + "的学生信息",
                            "时间": alter_time}

                xml_data = dicttoxml(log_file)
                dom = parseString(xml_data)
                xml_str = dom.toprettyxml(indent="  ")

                with open('log.xml', 'a', encoding='utf-8') as f:
                    f.write(xml_str)
                break
            else:
                pass

    def del_student(self):
        while True:
            try:
                with open('students_data.json', 'r', encoding='utf-8') as f:
                    data = json.load(f)
            except FileNotFoundError:
                print("文件未找到，请检查文件路径。")
                data = []
            del_data = input("请输入要删除学生信息的姓名")
            for student in data:
                if student["name"] == del_data:
                    data.remove(student)
                    print("删除成功！")
            alter_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            quit_del = input("0、退出    1、继续删除")

            if quit_del == "0":
                with open('students_data.json', 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=4)
                log_file = {"姓名": self.name, "工号": self.pid,
                            "操作": "删除" + student["name"] + "的学生信息", "时间": alter_time}

                xml_data = dicttoxml(log_file)
                dom = parseString(xml_data)
                xml_str = dom.toprettyxml(indent="  ")

                with open('log.xml', 'a', encoding='utf-8') as f:
                    f.write(xml_str)
                break
            else:
                pass

    def query_student(self):
        while True:
            try:
                df = pd.read_excel("students_dormitory.xlsx")

                student_name = input("请输入要查询的学生姓名：")

                result = df[df['name'] == student_name]
                if result.empty:
                    print(f"未找到名为 {student_name} 的学生信息。")
                else:
                    print("查询到的学生信息如下：")
                    print(result.to_csv(sep='\t'))

            except Exception as e:
                print(f"发生错误：{e}")
            query_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            quit_query = input("0、退出    1、继续查询")

            if quit_query == "0":

                log_file = {"姓名": self.name, "工号": self.pid,
                            "操作": "查询" + student_name + "的学生信息", "时间": query_time}

                xml_data = dicttoxml(log_file)
                dom = parseString(xml_data)
                xml_str = dom.toprettyxml(indent="  ")

                with open('log.xml', 'a', encoding='utf-8') as f:
                    f.write(xml_str)
                break
            else:
                pass


class dorm():
    def __init__(self, room_num, capacity):
        self.room_num = 200
        self.capacity = 4
        self.building = ["1号楼", "2号楼"]

        with open('students_data.json', 'r', encoding='utf-8') as json_file:
            self.students_data = json.load(json_file)
        self.male_dormitory = {f"1号楼{str(i)}": [] for i in range(1, 201)}
        self.female_dormitory = {f"2号楼{str(i)}": [] for i in range(1, 201)}

    def auto_allocate_dorm(self):
        for student in self.students_data:
            if student["gender"] == "男":
                for dorm, students_in_dorm in self.male_dormitory.items():
                    if len(students_in_dorm) < 4:
                        students_in_dorm.append(student)
                        student["dorm_id"] = dorm
                        break
            else:
                for dorm, students_in_dorm in self.female_dormitory.items():
                    if len(students_in_dorm) < 4:
                        students_in_dorm.append(student)
                        student["dorm_id"] = dorm
                        break

        df = pd.DataFrame(self.students_data)
        excel_file_path ='students_dormitory.xlsx'
        try:
            df.to_excel(excel_file_path, index=False)
            print(f"学生信息和宿舍信息已成功保存到 {excel_file_path}")
        except Exception as e:
            print(f"保存 Excel 文件时出现错误: {e}")

    def change_dorm(self):
        df = pd.read_excel("students_dormitory.xlsx")
        student_name = input("请输入要更换宿舍的学生姓名：")
        student_index = df[df['name'] == student_name].index
        new_dormitory = input(f"请输入{student_name}的新宿舍")
        target_dorm_students = df[df['dorm_id'] == new_dormitory]
        if len(target_dorm_students) >= 4:
            print("更换失败，该宿舍已满！")
        else:
            df.loc[student_index[0], 'dorm_id'] = new_dormitory
            df.to_excel("students_dormitory.xlsx", index=False)
            print("已成功将{student_name}的宿舍修改为{new_dormitory}。")
            return student_name

    def del_dorm(self):
        df = pd.read_excel("students_dormitory.xlsx")
        student_name = input("请输入要退宿的学生姓名：")
        student_index = df[df['name'] == student_name].index
        if len(student_index) == 0:
            print(f"未找到名为 {student_name} 的学生信息，无法退宿。")
        else:
            df = df.drop(student_index[0])
            df.to_excel("students_dormitory.xlsx", index=False)
            print(f"已成功删除 {student_name} 的宿舍信息，该学生已退宿。")
            return student_name


class administrate(Person):
    def __init__(self, name, id):
        super().__init__(name, id)

    def display_info(self):
        print(f"姓名: {self._name}, 工号: {self.pid}")

    def allocate_dorm(self):
        dorm1 = dorm(200, 4)
        dorm1.auto_allocate_dorm()
        auto_allocate_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_file = {"姓名": self.name, "工号": self.pid,
                    "操作": "自动分配学生宿舍", "时间": auto_allocate_time}

        try:
            log_csv = pd.read_csv("allocation_log.csv")
        except FileNotFoundError:
            log_csv = pd.DataFrame(columns=log_file.keys())
        log_df = pd.DataFrame([log_file])
        combined_df = pd.concat([log_csv, log_df], ignore_index=True)
        combined_df.to_csv("allocation_log.csv", index=False, encoding='utf-8')

    def change_dorm(self):
        dorm1 = dorm(200, 4)
        student_name = dorm1.change_dorm()

        change_dorm_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_file = {"姓名": self.name, "工号": self.pid,
                    "操作": "更换" + student_name + "的宿舍", "时间": change_dorm_time}

        try:
            log_csv = pd.read_csv("allocation_log.csv")
        except FileNotFoundError:
            log_csv = pd.DataFrame(columns=log_file.keys())
        log_df = pd.DataFrame([log_file])
        combined_df = pd.concat([log_csv, log_df], ignore_index=True)
        combined_df.to_csv("allocation_log.csv", index=False, encoding='utf-8')

    def del_dorm(self):
        dorm1 = dorm(200, 4)
        student_name = dorm1.del_dorm()
        change_dorm_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_file = {"姓名": self.name, "工号": self.pid,
                    "操作": student_name + "已成功办理退宿", "时间": change_dorm_time}

        try:
            log_csv = pd.read_csv("allocation_log.csv")
        except FileNotFoundError:
            log_csv = pd.DataFrame(columns=log_file.keys())
        log_df = pd.DataFrame([log_file])
        combined_df = pd.concat([log_csv, log_df], ignore_index=True)
        combined_df.to_csv("allocation_log.csv", index=False, encoding='utf-8')


def main():
    while True:
        students = []
        login_code = input("请登录账号")
        if login_code == "1000":
            print("教师账号登录成功")
            teacher1 = teacher("教师", "1000")
            print("1、学生信息管理   2、宿舍信息查询  3、退出系统")
            sub_choice = input("请选择操作")
            if sub_choice == "1":
                print("1、添加学生    2、修改学生信息   3、删除学生信息 ")
                sub_choice1 = input("学生信息管理：请选择操作")
                if sub_choice1 == "1":
                    teacher1.add_student(students)
                elif sub_choice1 == "2":
                    teacher1.alter_student()
                elif sub_choice1 == "3":
                    teacher1.del_student()
            elif sub_choice == "2":
                teacher1.query_student()
        elif login_code == "2000":
            print("管理员账号登录成功")
            admin1 = administrate("管理员", 2000)
            admin_choice = input("1、自动分配宿舍(按专业)    2、更换宿舍    3、退宿    4、退出系统")
            if admin_choice == "1":
                admin1.allocate_dorm()
            elif admin_choice == "2":
                admin1.change_dorm()
            elif admin_choice == "3":
                admin1.del_dorm()
            elif admin_choice == "4":
                break
        else:
            print("输入错入，请重新输入")


if __name__ == '__main__':
    main()

